/**************************************************************************//**
 * @item     CosyOS Config
 * @file     mcucfg_8051.h
 * @brief    8051 Core Config File
 * @author   迟凯峰
 * @version  V2.3.5
 * @date     2023.05.10
 ******************************************************************************/

#ifndef __MCUCFG_8051_H
#define __MCUCFG_8051_H

/******************************************************************************
 *                             USER Definitions                               *
 ******************************************************************************/

          //*** <<< Use Configuration Wizard in Context Menu >>> ***//

///////////////////////////////////////////////////////////////////////////////
// <s> 标准头文件
// <i> 定义与您的MCU相匹配的标准头文件，您的c文件中可不必再包含此文件。
// <i> 示例一：reg51.h
// <i> 示例二：..\MCU\reg51.h，此种包含路径的写法，在图形用户界面输入时有时会出问题，建议在文本编辑界面中定义或加强校对。
#define MCUCFG_STANDARDHEAD             "reg51.h"
///////////////////////////////////////////////////////////////////////////////
// <o> 系统时钟
// <i> 告知CosyOS您所配置的系统时钟，单位为MHZ。
#define MCUCFG_SYSFOSC                  24
#if !MCUCFG_SYSFOSC
#error 非法的设置值！
#endif
///////////////////////////////////////////////////////////////////////////////
// <o> 系统时钟分频系数
// <i> 告知CosyOS您所配置的系统时钟分频系数，取值范围：<1~255>。
#define MCUCFG_SYSFOSCDIV               1
#if !MCUCFG_SYSFOSCDIV
#error 非法的设置值！
#endif
///////////////////////////////////////////////////////////////////////////////
// <o> 最低优先级中断寄存器库
// <0=> bank0 <1=> bank1 <2=> bank2 <3=> bank3
// <i> 所有最低优先级中断的寄存器库，bank0为不使用独立的寄存器库。
#define MCUCFG_STKREGBANK               0
///////////////////////////////////////////////////////////////////////////////
// <q> 第二组DPTR寄存器
// <i> 告知CosyOS您是否启用第二组DPTR寄存器，如果您的MCU没有第二组DPTR寄存器，请勿勾选。
#define MCUCFG_DOUBLEDPTR               0
///////////////////////////////////////////////////////////////////////////////
// <h> PendSV_Handler
// <i> 由于51单片机没有PendSV_Handler软中断，您应专门配置一个硬件中断用于代替PendSV_Handler。
// <i> 您可选择一个未使用的硬件中断，并在初始化钩子中配置它，注意优先级应为最低级。

// <o> 中断号
// <i> 中断号
#define MCUCFG_PSVIRQ                   

// <o> 中断关闭
// <i> 此项您应在文本编辑界面中定义。
// <i> 示例：EX0 = 0
#define mPSV_Disable                    

// <o> 中断开启
// <i> 此项您应在文本编辑界面中定义。
// <i> 示例：EX0 = 1
#define mPSV_Enable                     

// <o> 中断触发
// <i> 置中断标志位
// <i> 此项您应在文本编辑界面中定义。
// <i> 示例：IE0 = 1
#define mPSV_Trigger                    

// <o> 中断清零
// <i> 清中断标志位
// <i> 此项您应在文本编辑界面中定义。
// <i> 示例：IE0 = 0
#define mPSV_Clear                      

// <o> 异步服务总数
// <i> 取值范围：<2~64>
// <i> 对于51单片机，您在中断中每调用一次异步服务，都要输入一个唯一的服务ID，此项用于定义您在中断中调用异步服务的总次数。
// <i> 示例：如果异步服务总数为10，那么您在中断中最多只能调用10次异步服务，服务ID为0~9。
#define MCUCFG_ISVTOTAL                 2
#if MCUCFG_ISVTOTAL < 2 || MCUCFG_ISVTOTAL > 64
#error 非法的设置值！
#endif

// </h>
///////////////////////////////////////////////////////////////////////////////
// <h> 内存优化
// <i> 内存优化是为了能让用户自由配置一部分系统变量的存储域，以达到最佳的内存利用率和尽可能的提高性能。
// <i> 每一项应尽可能的配置为更高性能的内存。

// <o> 定时中断内存
// <0=> data <1=> idata <2=> pdata <3=> xdata
// <i> 定时中断内存
#define __MCUCFG_MEMOPT1                3
#if   __MCUCFG_MEMOPT1 == 0
#define _TIMINT_MEM_                    data
#elif __MCUCFG_MEMOPT1 == 1
#define _TIMINT_MEM_                    idata
#elif __MCUCFG_MEMOPT1 == 2
#define _TIMINT_MEM_                    pdata
#elif __MCUCFG_MEMOPT1 == 3
#define _TIMINT_MEM_                    xdata
#endif

// <o> 定时查询内存
// <0=> data <1=> idata <2=> pdata <3=> xdata
// <i> 定时查询内存
#define __MCUCFG_MEMOPT2                3
#if   __MCUCFG_MEMOPT2 == 0
#define _TIMQRY_MEM_                    data
#elif __MCUCFG_MEMOPT2 == 1
#define _TIMQRY_MEM_                    idata
#elif __MCUCFG_MEMOPT2 == 2
#define _TIMQRY_MEM_                    pdata
#elif __MCUCFG_MEMOPT2 == 3
#define _TIMQRY_MEM_                    xdata
#endif

// <o> DEBUG高速内存
// <0=> data <1=> idata <2=> pdata <3=> xdata
// <i> DEBUG高速内存
#define __MCUCFG_MEMOPT31               3
#if   __MCUCFG_MEMOPT31 == 0
#define _DEBUG_HMEM_                    data
#elif __MCUCFG_MEMOPT31 == 1
#define _DEBUG_HMEM_                    idata
#elif __MCUCFG_MEMOPT31 == 2
#define _DEBUG_HMEM_                    pdata
#elif __MCUCFG_MEMOPT31 == 3
#define _DEBUG_HMEM_                    xdata
#endif

// <o> DEBUG中速内存
// <0=> data <1=> idata <2=> pdata <3=> xdata
// <i> DEBUG中速内存
#define __MCUCFG_MEMOPT32               3
#if   __MCUCFG_MEMOPT32 == 0
#define _DEBUG_MMEM_                    data
#elif __MCUCFG_MEMOPT32 == 1
#define _DEBUG_MMEM_                    idata
#elif __MCUCFG_MEMOPT32 == 2
#define _DEBUG_MMEM_                    pdata
#elif __MCUCFG_MEMOPT32 == 3
#define _DEBUG_MMEM_                    xdata
#endif

// <o> 常量内存
// <0=> data <1=> idata <2=> pdata <3=> xdata <4=> code
// <i> 常量内存
#define __MCUCFG_MEMOPT4                4
#if __MCUCFG_MEMOPT4 == 0
#define _CONST_MEM_                     data
#elif __MCUCFG_MEMOPT4 == 1
#define _CONST_MEM_                     idata
#elif __MCUCFG_MEMOPT4 == 2
#define _CONST_MEM_                     pdata
#elif __MCUCFG_MEMOPT4 == 3
#define _CONST_MEM_                     xdata
#elif __MCUCFG_MEMOPT4 == 4
#define _CONST_MEM_                     code
#endif

// </h>
///////////////////////////////////////////////////////////////////////////////
// <h> 动态内存设置
// <i> CosyOS会使用下列参数自动初始化内存池。

// <o> 内存池指针
// <i> 内存池的起始内存地址
#define MCUCFG_MALLOCMEMBPTR            4096
#if !MCUCFG_MALLOCMEMBPTR
#error 非法的设置值！
#endif

// <o> 内存池大小
// <i> 内存池的大小（字节数）
#define MCUCFG_MALLOCMEMSIZE            4096
#if !MCUCFG_MALLOCMEMSIZE
#error 非法的设置值！
#endif

// </h>
///////////////////////////////////////////////////////////////////////////////

                //*** <<< end of configuration section >>> ***//

/******************************************************************************
 *                               OS Definitions                               *
 ******************************************************************************/

/* Header */
#include <string.h>
#include <intrins.h>
#include MCUCFG_STANDARDHEAD
#include "..\System\vardef.h"

/* Memory */
#define _CODE_MEM_    code
#define _STACK_MEM_   idata
#define _SYS_MEM_     data
#define _TASK_MEM_    xdata
#define _SV_MEM_      xdata
#ifndef _MALLOC_MEM_
#define _MALLOC_MEM_  xdata
#endif
#if SYSCFG_TASKCREATEMODE == __STATIC__ || SYSCFG_TASKCREATEMODE == __BALANCE__
#define _THDL_MEM_    _MALLOC_MEM_
#elif SYSCFG_TASKCREATEMODE == __DYNAMIC__
#define _THDL_MEM_    _TASK_MEM_
#endif
#define _DEBUG_LMEM_  xdata

/* Register */
#define _SYS_REG_     _SYS_MEM_
#define _DEBUG_HREG_  _DEBUG_HMEM_
#define _DEBUG_LREG_  _DEBUG_MMEM_

/* Typedef */
typedef bit   tBIT;
typedef u8    tSP;
typedef u8    tStackSize;
typedef u8    tDM;
typedef u16   tPC;
typedef u32   tGRP;
typedef u16   tSysTick;

/* Extern */
extern bit vISV_FF;
extern tSP _SYS_MEM_ vMSP;
extern tSP _SYS_MEM_ vBSP;
extern u16 _TASK_MEM_ vISS[MCUCFG_ISVTOTAL];

/* * */
#define MCUCFG_MCUARC           !__ARM__
#define MCUCFG_MCULEVEL         __FEIPAOZI__
#define MCUCFG_TASKSTACKMONITOR __DISABLED__
#if MCUCFG_STKREGBANK
#define __USING__               using MCUCFG_STKREGBANK
#define __REGSIZE__             8
#define __BASICSTACKSIZE__      (MCUCFG_DOUBLEDPTR ? 9 : 7)
#else
#define __USING__
#define __REGSIZE__             0
#define __BASICSTACKSIZE__      (MCUCFG_DOUBLEDPTR ? 17 : 15)
#endif
#define __C51USING__            __USING__
#define __STK_ATTRIBUTE__       interrupt 1 __USING__
#define __PSV_ATTRIBUTE__       interrupt MCUCFG_PSVIRQ __USING__
#define __REENTRANT__           reentrant
#define __BSP_ALIGN__
#define MCUCFG_DIRMSGTYPE       0
#define __DM_PSP__
#define __DM_SIZE__             (&mx - &m0 - 1)
#if SYSCFG_DIRMSGMODE == __PERFORMANCE__
#define __DM_VAR__              tDM m0_
#define __DM_VAL__              1
#elif SYSCFG_DIRMSGMODE == __INTELLIGENT__
#define __DM_VAR__              tDM R3_, tDM R5_, tDM R7_, tDM m0_
#define __DM_VAL__              0, 0, 0, 1
#endif
#define __STACKSIZE_TASKMGR__   (__BASICSTACKSIZE__ + 16)
#define __STACKSIZE_DEBUGGER__  (__BASICSTACKSIZE__ + 16)
#define __STACKSIZE_STARTER__   (__BASICSTACKSIZE__ + 16)
#define __STACKSIZE_SYSIDLE__   (__BASICSTACKSIZE__ + 16)

/* API */
#define mSysTick_InitValue    (65536 - (1UL * MCUCFG_SYSFOSC * SYSCFG_STKCYCLE) / MCUCFG_SYSFOSCDIV / 12)
#define mSysTick_Cycle        (65536 - mSysTick_InitValue)
#define mSysTick_Counter      ((TH0 << 8) | TL0)
#define mSTK_Disable          ET0 = 0
#define mSTK_Enable           ET0 = 1
#define mTaskNode_Head_       tStackSize stacklen;
#if __REGSIZE__
#define mTaskNode_Tail_       u8 reg[__REGSIZE__];
#define mReg_PUSH	\
	*(u32 *)(vTASKING->reg + 0) = *(u32 _SYS_MEM_ *)0;	\
	*(u32 *)(vTASKING->reg + 4) = *(u32 _SYS_MEM_ *)4
#define mReg_POP	\
	*(u32 _SYS_MEM_ *)0 = *(u32 *)(vTASKING->reg + 0);	\
	*(u32 _SYS_MEM_ *)4 = *(u32 *)(vTASKING->reg + 4)
#else
#define mTaskNode_Tail_
#define mReg_PUSH do{}while(false)
#define mReg_POP  do{}while(false)
#endif

#define mDisableIRQ	EA = 0
#define mEnableIRQ	EA = 1

#define mEnterCritical	\
do{	\
	mPSV_Disable;	\
	mSTK_Disable;	\
}while(false)

#define mExitCritical	\
do{	\
	mSTK_Enable;	\
	mPSV_Enable;	\
}while(false)

#define mSys_Idle	\
do{	\
	PCON |= 0x01;	\
	OS_NOPxX;	\
}while(false)

#define mSys_INIT	\
do{	\
	vMSP = SP;	\
	vBSP = SP + 1;	\
	__init_mempool((void _MALLOC_MEM_ *)MCUCFG_MALLOCMEMBPTR, MCUCFG_MALLOCMEMSIZE);	\
	OS_NOPx1;	\
	TMOD &= 0xF0;	\
	TL0 = (u8)(mSysTick_InitValue);	\
	TH0 = (u8)(mSysTick_InitValue >> 8);	\
	TR0 = 1;	\
	mSTK_Enable;	\
	mPSV_Enable;	\
	EA = 1;	\
}while(false)

#define mTaskmgr_Counting	\
	counter2 = (counter1 * 100 * 12 * MCUCFG_SYSFOSCDIV) / MCUCFG_SYSFOSC / counter2

#define mSTK_Counting	\
do{	\
	if(mSysTick_Counter <= tick_temp) break;	\
	vSTK_Counter1 += mSysTick_Counter - tick_temp;	\
	vSTK_Counter2++;	\
}while(false)

#define mScheduler_INIT	\
	u8 _STACK_MEM_  * _SYS_REG_ msp8;	\
	u8 _MALLOC_MEM_ * _SYS_REG_ psp8;	\
	bit vPUSH_f = false;	\
	vScheduling_f = false

#define mTaskStack_INIT	\
do{	\
	*(u16 *)node_news->BSP = ((u16)vACTBUF->entry << 8) | ((u16)vACTBUF->entry >> 8);	\
	*(u8 *)(node_news->BSP + (MCUCFG_DOUBLEDPTR ? 9 : 7) - 1) = 0;	\
	node_news->stacklen = __BASICSTACKSIZE__;	\
}while(false)

#define mTaskStack_LEN	\
	stacklen = SP - vMSP

#define mEvery_Monitor do{}while(false)
#define mEntry_Monitor do{}while(false)

#if SYSCFG_TASKCREATEMODE == __STATIC__
#define mPUSH_Monitor	\
do{	\
	if(vTASKING->stacksize < stacklen)	\
	{	\
		vTASKING->state = __STOPPED_TSOF__;    \
		vFault.overflow_taskstack = true;  \
	}	\
	else	\
	{	\
		vPUSH_f = true;	\
		if(vTASKING->TPL > node_news->TPL)	\
		{	\
			vTASKING->counter = 0;	\
		}	\
	}	\
}while(false)
#else
#define mPUSH_Monitor	\
do{	\
	if(vTASKING->stacksize < stacklen)	\
	{	\
		vTASKING->stacksize = stacklen;	\
		__free(vTASKING->BSP);	\
		vTASKING->BSP = NULL;	\
		vTASKING->BSP = (u8 *)__malloc(vTASKING->stacksize);	\
		if(vTASKING->BSP != NULL)	\
		{	\
			vTASKING->realloc = true;	\
			vAlarm.realloc_taskstack = true;	\
			vPUSH_f = true;	\
		}	\
		else	\
		{	\
			vTASKING->state = __STOPPED_TSRF__;	\
			vFault.reallocfail_taskstack = true;	\
		}	\
	}	\
	else	\
	{	\
		vPUSH_f = true;	\
	}	\
	if(vPUSH_f)	\
	{	\
		if(vTASKING->TPL > node_news->TPL)	\
		{	\
			vTASKING->counter = 0;	\
		}	\
	}	\
}while(false)
#endif

#if SYSCFG_TASKPCMONITOR == __ENABLED__
#define mTaskPC_Monitor	\
do{	\
	if(!vTaskmgrBinary) break;	\
	vPC = *(tPC *)(SP + 1 - __BASICSTACKSIZE__);	\
	vPC = (vPC << 8) | (vPC >> 8);	\
}while(false)
#else
#define mTaskPC_Monitor do{}while(false)
#endif

#define mUsedTime_END	\
do{	\
	if(usedtime[0])	\
	{	\
		usedtime[0]--;	\
		usedtime[1] = 65536 - usedtime[1] + counter - mSysTick_InitValue;	\
	}	\
	else	\
	{	\
		if(counter >= usedtime[1])	\
		{	\
			usedtime[1] = counter - usedtime[1];	\
		}	\
		else	\
		{	\
			usedtime[1] = 65536 - usedtime[1] + counter - mSysTick_InitValue;	\
		}	\
	}	\
	vTASKING->usedtime[0] += usedtime[0];	\
	vTASKING->usedtime[0] += (vTASKING->usedtime[1] + usedtime[1]) / mSysTick_Cycle;	\
	vTASKING->usedtime[1]  = (vTASKING->usedtime[1] + usedtime[1]) % mSysTick_Cycle;	\
}while(false)

#define mUsedTime_INIT	\
do{	\
	usedtime[0] = 0;	\
	usedtime[1] = counter;	\
}while(false)

#define mTaskStack_PUSH	\
do{	\
	if(!vPUSH_f) break;	\
	if(vTaskmgrBinary) mUsedTime_END;	\
	msp8 = (u8 _STACK_MEM_  *)vBSP;	\
	psp8 = (u8 _MALLOC_MEM_ *)vTASKING->BSP;	\
	vTASKING->stacklen = stacklen;	\
	do{	\
		*psp8++ = *msp8++;	\
	}while(--stacklen);	\
	mReg_PUSH;	\
	mTaskPC_Monitor;	\
}while(false)

#define mTaskStack_POP	\
do{	\
	if(vTaskmgrBinary) mUsedTime_INIT;	\
	vTASKING = node_news;	\
	msp8 = (u8 _STACK_MEM_  *)vBSP;	\
	psp8 = (u8 _MALLOC_MEM_ *)vTASKING->BSP;	\
	stacklen = vTASKING->stacklen;	\
	SP = vMSP + stacklen;	\
	do{	\
		*msp8++ = *psp8++;	\
	}while(--stacklen);	\
	mReg_POP;	\
}while(false)

#define mISV_Do(svid)	\
do{	\
	extern bit vISV_F##svid;	\
	vISS[svid] = (u16)&isv_;	\
	vISV_F##svid = true;	\
	vISV_FF = true;	\
	mPSV_Trigger;	\
}while(false)

#define mISV	\
	extern void __isv_handler(void);	\
	mPSV_Clear;	\
	if(vISV_FF) __isv_handler();	\
	if(!vScheduling_f) return

#define miWriteFlagBits	\
	static bit flag = false;	\
	if(!flag)	\
	{	\
		flag = true

#endif
